#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>
#include <sys/wait.h>

// 判断出拳结果
int result_announce(int a, int b) {
    if (a == b) return 0;                   // 平局
    if ((a == 0 && b == 1) ||               // 石头胜剪刀
        (a == 1 && b == 2) ||               // 剪刀胜布
        (a == 2 && b == 0))                 // 布胜石头
        return -1;                          // A胜
    return 1;                               // B胜
}

// 显示比赛结果
void displayResults(int *results, int rounds) {
    int wins_A = 0, wins_B = 0, draws = 0;
    
    for (int i = 0; i < rounds; i++) {
        switch(results[i]) {
            case -1: wins_A++; break;
            case 0: draws++; break;
            case 1: wins_B++; break;
        }
    }
    
    printf("\n=== 最终统计 ===\n");
    printf("A胜: %d次\n", wins_A);
    printf("B胜: %d次\n", wins_B);
    printf("平局: %d次\n", draws);
    printf("最终胜利者: %s\n", 
           wins_A > wins_B ? "A" : wins_B > wins_A ? "B" : "平局");
}

int main() {
    int rounds;                             // 比赛轮数
    int *result_list;                       // 存储每轮结果的数组
    int pipe_A[2], pipe_B[2];               // 两个管道：A和B
    pid_t pid_A, pid_B;                     // 两个子进程的PID
    
    srand(time(NULL));                      // 初始化随机数种子
    
    printf("请输入比赛轮数: ");
    scanf("%d", &rounds);                   // 获取用户输入的轮数
    
    result_list = malloc(rounds * sizeof(int));  // 为结果数组分配内存
    
    // 主循环：进行每一轮比赛
    for (int i = 0; i < rounds; i++) {
        // 创建管道A用于与选手A通信
        if (pipe(pipe_A) == -1) {
            perror("创建管道A失败");
            exit(EXIT_FAILURE);
        }
        
        // 创建管道B用于与选手B通信
        if (pipe(pipe_B) == -1) {
            perror("创建管道B失败");
            exit(EXIT_FAILURE);
        }
        
        // 创建选手A进程
        pid_A = fork();
        if (pid_A == 0) {                   // 子进程A
            close(pipe_A[0]);               // 关闭管道的读端
            srand(time(NULL) ^ getpid());   // 使用进程ID作为种子的一部分
            int choice = rand() % 3;        // 随机生成出拳(0-2)
            write(pipe_A[1], &choice, sizeof(choice));  // 将出拳写入管道
            close(pipe_A[1]);               // 关闭管道的写端
            exit(0);                        // 子进程退出
        }
        
        // 创建选手B进程
        pid_B = fork();
        if (pid_B == 0) {                   // 子进程B
            close(pipe_B[0]);               // 关闭管道的读端
            srand(time(NULL) ^ getpid() ^ 12345);  // 使用不同的种子
            int choice = rand() % 3;        // 随机生成出拳(0-2)
            write(pipe_B[1], &choice, sizeof(choice));  // 将出拳写入管道
            close(pipe_B[1]);               // 关闭管道的写端
            exit(0);                        // 子进程退出
        }
        
        // 父进程代码
        close(pipe_A[1]);                   // 关闭管道A的写端
        close(pipe_B[1]);                   // 关闭管道B的写端
        
        int choice_A, choice_B;             // 存储A和B的出拳
        
        // 从管道A读取选手A的出拳
        if (read(pipe_A[0], &choice_A, sizeof(choice_A)) == -1) {
            perror("读取A出拳失败");
            exit(EXIT_FAILURE);
        }
        
        // 从管道B读取选手B的出拳
        if (read(pipe_B[0], &choice_B, sizeof(choice_B)) == -1) {
            perror("读取B出拳失败");
            exit(EXIT_FAILURE);
        }
        
        close(pipe_A[0]);                   // 关闭管道A的读端
        close(pipe_B[0]);                   // 关闭管道B的读端
        
        // 等待两个子进程结束
        waitpid(pid_A, NULL, 0);
        waitpid(pid_B, NULL, 0);
        
        // 判断胜负并记录结果
        result_list[i] = result_announce(choice_A, choice_B);
        
        // 显示本轮结果
        char *choices[] = {"石头", "剪刀", "布"};
        printf("轮次%d: A出%s, B出%s -> %s\n", 
               i+1, 
               choices[choice_A], 
               choices[choice_B],
               result_list[i] == -1 ? "A胜" : 
               result_list[i] == 0 ? "平局" : "B胜");
        
        fflush(stdout);                     // 刷新输出缓冲区
    }
    
    displayResults(result_list, rounds);    // 显示最终结果
    
    free(result_list);                      // 释放结果数组内存
    
    return 0;                               // 程序正常退出
}